using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Newtonsoft.Json;
using AdminApiTemplate.Cache;
using AdminApiTemplate.Common.Exceptions;
using AdminApiTemplate.Common.Helpers;
using AdminApiTemplate.Common.Models;
using System.Text;

namespace AdminApiTemplate.Api.Filters
{
    /// <summary>
    /// 全局异常处理
    /// </summary>
    public class HttpGlobalExceptionFilter : IExceptionFilter
    {
        /// <summary>
        /// 全局异常处理
        /// </summary>
        /// <param name="context"></param>
        public void OnException(ExceptionContext context)
        {
            var sb = new StringBuilder();
            sb.AppendLine($"{context.HttpContext.Request.Method} {context.HttpContext.Request.Path}");

            var queryString = context.HttpContext.Request.QueryString.ToUriComponent();
            if (!string.IsNullOrEmpty(queryString))
            {
                sb.AppendLine($"QueryString:{queryString}");
            }

            if (context.HttpContext.Request.Body.CanRead)
            {
                context.HttpContext.Request.Body.Position= 0;
                using (var reader = new StreamReader(context.HttpContext.Request.Body))
                {
                    var body = reader.ReadToEndAsync().Result;
                    context.HttpContext.Request.Body.Position= 0;
                    sb.AppendLine($"Request:{body}");
                }
            }

            var requestId = RandomHelper.RequestId();
            var rsp = new ApiResponseBase<object>
            {
                ErrorCode = 999,
                ErrorMsg = "系统繁忙，请稍后再试",
                RequestId = requestId
            };

            var error = default(string);
            var wcex = context.Exception as WithCodeException;
            if (wcex != null)
            {
                rsp.ErrorCode= wcex.Code;
                rsp.ErrorMsg= wcex.Message;
                rsp.ErrorMsg2= wcex.Message2;
            }
            else
            {
                var wcex2 = context.Exception.InnerException as WithCodeException;
                if (wcex2 != null)
                {
                    rsp.ErrorCode = wcex2.Code;
                    rsp.ErrorMsg = wcex2.Message;
                    rsp.ErrorMsg2 = wcex2.Message2;
                }
                else
                {
                    error= context.Exception.ToString();
                }
            }

            var json = JsonConvert.SerializeObject(rsp, CacheHelper.ExcludeNullJsonConfig);
            sb.AppendLine($"Response:{json}");

            if (!string.IsNullOrEmpty(error))
            {
                sb.AppendLine($"Error:{error}");
            }

            LogHelper.WriteErrorAsync(sb.ToString());
            context.Result= new ContentResult
            {
                Content = json,
                ContentType = "application/json",
                StatusCode = 200,
            };
        }
    }
}
